package org.example.mock;

import lombok.extern.slf4j.Slf4j;
import org.example.bean.MovieReleaseAvg;

import java.math.BigDecimal;
import java.sql.*;
import java.util.*;

/**
 * 用于生成 MovieReleaseAvg 模拟数据的生成器类
 */
@Slf4j
public class MovieReleaseAvgGenerator {
    private static final String DB_URL = "jdbc:mysql://192.168.10.102/changchengfilm?requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final Random RANDOM = new Random();
    private static final int MIN_YEAR = 2005; // 最小年份限制
    private static final int MAX_YEAR = 2024; // 最大年份限制
    private static final int DATA_COUNT = 20; // 数据数量

    public static void main(String[] args) {
        log.info("开始生成 MovieReleaseAvg 模拟数据");

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // 生成20条数据，年份在2005-2024之间随机且不重复
            List<MovieReleaseAvg> dataList = generateMovieReleaseAvgData(DATA_COUNT, MIN_YEAR, MAX_YEAR);

            // 批量插入数据
            batchInsertData(conn, dataList);

            log.info("成功插入 {} 条数据", dataList.size());

            // 打印前10条数据作为示例
            for (int i = 0; i < Math.min(10, dataList.size()); i++) {
                log.info(dataList.get(i).toString());
            }
        } catch (SQLException e) {
            log.error("数据库操作失败", e);
        }
    }

    /**
     * 生成指定数量的 MovieReleaseAvg 模拟数据，年份随机且不重复
     * @param count 要生成的数据数量
     * @param minYear 最小年份
     * @param maxYear 最大年份（包含）
     */
    public static List<MovieReleaseAvg> generateMovieReleaseAvgData(int count, int minYear, int maxYear) {
        if (minYear < MIN_YEAR || maxYear > MAX_YEAR) {
            throw new IllegalArgumentException("年份范围必须在" + MIN_YEAR + "-" + MAX_YEAR + "之间");
        }

        if (count > (maxYear - minYear + 1)) {
            throw new IllegalArgumentException("无法生成" + count + "条不重复的数据，年份范围不足");
        }

        List<MovieReleaseAvg> resultList = new ArrayList<>();
        Set<Integer> usedYears = new HashSet<>(); // 记录已使用的年份

        while (resultList.size() < count) {
            // 生成随机年份
            int releaseYear = minYear + RANDOM.nextInt(maxYear - minYear + 1);

            // 如果年份已被使用，则重新生成
            if (usedYears.contains(releaseYear)) {
                continue;
            }

            usedYears.add(releaseYear);

            // 生成随机评分
            BigDecimal avgScore = generateRandomScore(0, 10);
            BigDecimal highestScore = generateRandomScore(avgScore.doubleValue(), 10);
            BigDecimal lowestScore = generateRandomScore(0, avgScore.doubleValue());

            resultList.add(new MovieReleaseAvg(releaseYear, avgScore, highestScore, lowestScore));
        }

        return resultList;
    }

    /**
     * 生成指定范围内的随机评分 (保留1位小数)
     */
    private static BigDecimal generateRandomScore(double min, double max) {
        if (min >= max) {
            return new BigDecimal(min).setScale(1, BigDecimal.ROUND_HALF_UP);
        }

        double randomValue = min + RANDOM.nextDouble() * (max - min);
        return new BigDecimal(randomValue).setScale(1, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 批量插入数据到数据库
     */
    private static void batchInsertData(Connection conn, List<MovieReleaseAvg> dataList) throws SQLException {
        String sql = "INSERT INTO movie_release_avg (release_year, avg_score, highest_score, lowest_score) " +
                "VALUES (?, ?, ?, ?)";

        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            conn.setAutoCommit(false);

            for (MovieReleaseAvg data : dataList) {
                pstmt.setInt(1, data.getReleaseYear());
                pstmt.setBigDecimal(2, data.getAvgScore());
                pstmt.setBigDecimal(3, data.getHighestScore());
                pstmt.setBigDecimal(4, data.getLowestScore());
                pstmt.addBatch();
            }

            pstmt.executeBatch();
            conn.commit();
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        } finally {
            conn.setAutoCommit(true);
        }
    }
}